Angular Custom Validator
In this tutorial, we shall see how to create a custom validator and assign it to a FormControl
.
Angular provides us with few in-built validators which can be used for validation. But there may be some scenarios in which we need to give custom validation to our control. In such a case, we create a custom validator.
Create an angular application
Let's start with an example program. First, create an angular application using
ng new angular-app
Then enter into the project using
cd angular-app
Add ReactiveFormsModule to the project
To use reactive forms, we need to import ReactiveFormsModule
in our app.module.ts
file.
Let's modify the code in our app.module.ts
to import the ReactiveFormsModule
and add it to imports
array.
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing-module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
AppRoutingModule,
ReactiveFormsModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Next, create a new component named, AddEmployeeComponent
using the following command.
ng g c add-employee
Let's modify the app-employee.component.ts
file
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-add-employee',
templateUrl: './add-employee.component.html',
styleUrls: ['./add-employee.component.css']
})
export class AddEmployeeComponent implements OnInit {
employeeForm: FormGroup;
gender = [
{ key: 'male', value: 'Male' },
{ key: 'female', value: 'Female' }
];
constructor(private fb: FormBuilder) { }
ngOnInit() {
this.employeeForm = this.fb.group({
name: ['', Validators.required],
age: ['', [Validators.required ]],
gender: ['', Validators.required]
});
}
onSubmit() {
console.log(this.employeeForm);
}
}
In ngOnInit()
life cycle event, we create a FormGroup
named employeeForm
and assign a FormGroup
by creating formGroup with the fb
which is a FormBuilder
.
The FormGroup
contains 3 FormControl
named name
, age
and gender
. The name
and gender
FormControl
's contains default value of empty string
and a singlerequired
validator.
Similarly, for age
FormControl
, we assign a default value of empty
string and to this control we are going to apply multiple validation to this control, so we use array([]
) notation for it. So the code looks something like below.
ngOnInit() {
this.employeeForm = this.fb.group({
name: ['', Validators.required],
age: ['', [Validators.required ]],
gender: ['', Validators.required]
});
}
Let's create a custom validator and assign it to the age
FormControl.
Create Custom Validator
Create a folder named custom-validator
and create a file named age-validator.ts
and modify the code as below.
import { FormControl } from '@angular/forms';
export function ageValidator(formControl: FormControl): { [key: string]: boolean } | null {
const age = formControl.value;
console.log(age);
if (age > 80) {
return { ageInValid: true };
}
return null;
}
The ageValidator
gets a FormControl
as input.
First, get the value from the FormControl
using the value
property and assign it to age
variable.
If the age
is greater that 80, then set ageInValid
property which is the custom validation property to true
and return the object.
If the age
is less that 80, then return null
which represents no validation error.
Adding the Custom Validator to FormControl
Next, add the custom validator to the age
FormControl
by adding the ageValidator
to validator array of AddEmployeeComponent
.
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ageValidator } from '../custom-validator/age.validator';
@Component({
selector: 'app-add-employee',
templateUrl: './add-employee.component.html',
styleUrls: ['./add-employee.component.css']
})
export class AddEmployeeComponent implements OnInit {
employeeForm: FormGroup;
gender = [
{ key: 'male', value: 'Male' },
{ key: 'female', value: 'Female' }
];
constructor(private fb: FormBuilder) { }
ngOnInit() {
this.employeeForm = this.fb.group({
name: ['', Validators.required],
age: ['', [Validators.required, ageValidator]],
gender: ['', Validators.required]
});
}
onSubmit() {
console.log(this.employeeForm);
}
}
Show up the validation message in HTML Template
In add-employee.component.html
file, we modify the code as below
<div>
<form [formGroup]='employeeForm' (ngSubmit)='onSubmit()'>
<div>
<label for='name'>Employee Name</label>
<input type='text' formControlName='name' />
<span *ngIf="!employeeForm.get('name').valid && employeeForm.get('name').touched">
Name is required!
</span>
</div>
<div>
<label for='age'>Employee Age</label>
<input type='number' formControlName='age' />
<span
*ngIf="!employeeForm.get('age').valid && employeeForm.get('age').touched && employeeForm.get('age').errors.required">
Age is required!
</span>
<span
*ngIf="!employeeForm.get('age').valid && employeeForm.get('age').touched && employeeForm.get('age').errors.ageInValid">
Age should not exceed 80!
</span>
</div>
<div>
<label for='age'>Employee Age</label>
<select formControlName='gender'>
<option>--select--</option>
<option *ngFor='let item of gender' [value]='item.key'>
{{item.value}}
</option>
</select>
</div>
<div>
<input type='submit' value='Submit' [disabled]='!employeeForm.valid' />
</div>
</form>
</div>
In the above example, we have set the validation for name
, age
and gender
FormControls.
To check whether there is validation error for the name
FormControl
, we get the FormControl
from employeeForm
as below.
employeeForm.get('age')
Now, we check whether the control's valid
property is false
and the control has been touched
and also check whether their is ageInValid
error for the control.
!employeeForm.get('age').valid && employeeForm.get('age').touched && employeeForm.get('age').errors.ageInValid
If the age entered is greater than 80, then the custom validator will set ageInValid
to true
. Now you can apply the selector string app-add-employee
to the app.component.ts
to make use of it.